package org.mili.ticketeer.dao;

import org.mili.application.dao.AbstractDao;
import org.mili.application.dao.DaoException;
import org.mili.application.dao.MofificationType;
import org.mili.application.dao.RowTransformer;
import org.mili.application.dao.query.QueryBuilder;
import org.mili.ticketeer.dto.Contact;
import org.mili.ticketeer.dto.ContactRole;
import org.mili.application.dto.Identifieable;
import org.mili.ticketeer.dto.Role;
import org.mili.application.util.Lambda;
import org.mili.application.util.Log;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class ContactRoleDao extends AbstractDao {

    public ContactRoleDao() {
        super(ContactRole.UniqueFields.values(), ContactRole.Fields.values(), ContactRole.TABLE);
    }

    public Boolean assign(final Contact contact, final Role role) throws DaoException {
        return doInDao(new Lambda<Boolean>() {
            @Override
            public Boolean exec(Object... params) throws SQLException, DaoException {
                ContactRole contactRole = new ContactRole();
                contactRole.setContact(contact.getId());
                contactRole.setRole(role.getId());
                boolean result = update("insert into `contact_role` (`contact`, `role`) values(?, ?);", contact.getId(),
                        role.getId()) == 1;
                boolean archive = archive(contactRole, MofificationType.CREATE) == 1;
                return result && archive;
            }
        });
    }

    public Boolean unassign(final Contact contact, final Role role) throws DaoException {
        return doInDao(new Lambda<Boolean>() {
            @Override
            public Boolean exec(Object... params) throws SQLException, DaoException {
                ContactRole contactRole = new ContactRole();
                contactRole.setContact(contact.getId());
                contactRole.setRole(role.getId());
                boolean result = update("delete from `contact_role` where `contact`=? and `role`=?", contact.getId(),
                        role.getId()) == 1;
                boolean archive = archive(contactRole, MofificationType.DELETE) == 1;
                return result && archive;
            }
        });
    }

    public List<ContactRole> getContactRolesFor(final Contact contact) throws DaoException {
        return doInDao(new Lambda<List<ContactRole>>() {
            @Override
            public List<ContactRole> exec(Object... params) throws SQLException {
                return query(new RowTransformer<ContactRole>() {
                    @Override
                    public ContactRole transform(ResultSet resultSet) throws SQLException {
                        ContactRole contactRole = new ContactRole();
                        contactRole.setContact(resultSet.getInt("contactid"));
                        contactRole.setRole(resultSet.getInt("roleid"));
                        Log.log(this, "getContactRolesFor", "contact=%s, %s", contact.getId(), contactRole);
                        return contactRole;
                    }
                }, "select role.id as roleid, (select contact_role.contact from contact_role where contact_role.role=roleid and contact_role.contact=?) as contactid from role", contact.getId());
            }
        });
    }

    public List<ContactRole> getAssignedContactRolesFor(final Contact contact) throws DaoException {
        return doInDao(new Lambda<List<ContactRole>>() {
            @Override
            public List<ContactRole> exec(Object... params) throws SQLException {
                return query(new RowTransformer<ContactRole>() {
                    @Override
                    public ContactRole transform(ResultSet resultSet) throws SQLException {
                        ContactRole contactRole = new ContactRole();
                        contactRole.setContact(contact.getId());
                        contactRole.setRole(resultSet.getInt(ContactRole.Fields.ROLE.name()));
                        Log.log(this, "getAssignedContactRolesFor", "contact=%s, %s", contact.getId(), contactRole);
                        return contactRole;
                    }
                }, QueryBuilder.createQueryBuilder().select().fields(ContactRole.Fields.ROLE).from(ContactRole.TABLE)
                        .where().eq(ContactRole.Fields.CONTACT, contact.getId()).build());
            }
        });
    }

    public List<ContactRole> getContactRoles() throws DaoException {
        return doInDao(new Lambda<List<ContactRole>>() {
            @Override
            public List<ContactRole> exec(Object... params) throws SQLException {
                return query(new RowTransformer<ContactRole>() {
                    @Override
                    public ContactRole transform(ResultSet resultSet) throws SQLException {
                        ContactRole contactRole = new ContactRole();
                        contactRole.setRole(resultSet.getInt("role"));
                        return contactRole;
                    }
                },
                        QueryBuilder.createQueryBuilder()
                                .select()
                                .fields(Identifieable.Fields.ID)
                                .from(table)
                                .build());
            }
        });
    }

}
